/*
 * Copyright 2025, AutoMQ HK Limited.
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.automq.stream.s3.objects;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

public class CommitStreamSetObjectRequest {

    /**
     * The object id of the stream set object.
     */
    private long objectId;

    /**
     * The order id of the stream set object.
     * <p>
     * When the stream set object is generated by compacting, the order id is the first compacted object's order id.
     */
    private long orderId;

    /**
     * The real size of the stream set object in Storage.
     */
    private long objectSize;
    /**
     * The stream ranges of the stream set object.
     * <p>
     * The stream ranges are sorted by <code>[stream][epoch][startOffset]</code>
     */
    private List<ObjectStreamRange> streamRanges;

    /**
     * The stream objects which split from the stream set object.
     * <p>
     * The stream objects are sorted by <code>[stream][startOffset]</code>
     */
    private List<StreamObject> streamObjects;

    /**
     * The object ids which are compacted by the stream set object.
     */
    private List<Long> compactedObjectIds;

    /**
     * The generated object's attributes.
     */
    private int attributes = ObjectAttributes.UNSET.attributes();

    public long getObjectId() {
        return objectId;
    }

    public void setObjectId(long objectId) {
        this.objectId = objectId;
    }

    public long getObjectSize() {
        return objectSize;
    }

    public void setObjectSize(long objectSize) {
        this.objectSize = objectSize;
    }

    public List<Long> getCompactedObjectIds() {
        return Objects.requireNonNullElse(compactedObjectIds, Collections.emptyList());
    }

    public void setCompactedObjectIds(List<Long> compactedObjectIds) {
        this.compactedObjectIds = compactedObjectIds;
    }

    public List<ObjectStreamRange> getStreamRanges() {
        if (streamRanges == null) {
            return Collections.emptyList();
        }
        return streamRanges;
    }

    public void setStreamRanges(List<ObjectStreamRange> streamRanges) {
        this.streamRanges = streamRanges;
    }

    public void addStreamRange(ObjectStreamRange streamRange) {
        if (streamRanges == null) {
            streamRanges = new LinkedList<>();
        }
        streamRanges.add(streamRange);
    }

    public List<StreamObject> getStreamObjects() {
        if (streamObjects == null) {
            return Collections.emptyList();
        }
        return streamObjects;
    }

    public void setStreamObjects(List<StreamObject> streamObjects) {
        this.streamObjects = streamObjects;
    }

    public void addStreamObject(StreamObject streamObject) {
        if (streamObjects == null) {
            streamObjects = new LinkedList<>();
        }
        streamObjects.add(streamObject);
    }

    public long getOrderId() {
        return orderId;
    }

    public void setOrderId(long orderId) {
        this.orderId = orderId;
    }

    public int getAttributes() {
        return attributes;
    }

    public void setAttributes(int attributes) {
        this.attributes = attributes;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[CommitStreamSetObjectRequest]:");
        sb.append("streamSetObjectId=").append(objectId).append(", attr=").append(attributes).append(", compactedObjects=").append(compactedObjectIds);
        sb.append(", \n\tstreamRanges=");
        getStreamRanges().forEach(range -> {
            sb.append("(si=").append(range.getStreamId()).append(", so=").append(range.getStartOffset()).append(", eo=")
                .append(range.getEndOffset()).append("), ");
        });
        sb.append(", \n\tstreamObjects=");
        getStreamObjects().forEach(obj ->
            sb.append("(si=").append(obj.getStreamId())
                .append(", so=").append(obj.getStartOffset())
                .append(", eo=").append(obj.getEndOffset())
                .append(", oi=").append(obj.getObjectId())
                .append(", size=").append(obj.getObjectSize())
                .append(", attr=").append(obj.getAttributes())
                .append("), "));
        return sb.toString();
    }
}
